package mysql

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"logs"
)

type Process struct {
	Id      int    `gorm:"primary_key;auto_increment"`
	NowTime string `gorm:"type:varchar(100);not null"`
	Lan     string `gorm:"type:varchar(20);not null"`
	Ip      string `gorm:"type:varchar(20);not null"`
	Process string `gorm:"type:varchar(256)"`
}

type Host struct {
	Id                   int    `gorm:"primary_key;auto_increment"`
	NowTime              string `gorm:"type:varchar(100);not null"`
	Lan                  string `gorm:"type:varchar(20);not null"`
	Ip                   string `gorm:"type:varchar(20);not null"`
	Hostname             string `gorm:"type:varchar(256)"`
	Uptime               string `gorm:"type:varchar(100)"`
	BootTime             string `gorm:"type:varchar(100)"`
	Procs                string `gorm:"type:varchar(100)"`
	Os                   string `gorm:"type:varchar(100)"`
	Platform             string `gorm:"type:varchar(100)"`
	PlatformFamily       string `gorm:"type:varchar(100)"`
	PlatformVersion      string `gorm:"type:varchar(100)"`
	KernelVersion        string `gorm:"type:varchar(100)"`
	VirtualizationSystem string `gorm:"type:varchar(100)"`
	VirtualizationRole   string `gorm:"type:varchar(100)"`
	Hostid               string `gorm:"type:varchar(100)"`
}

type CpuLoad struct {
	Id      int    `gorm:"primary_key;auto_increment"`
	NowTime string `gorm:"type:varchar(100);not null"`
	Lan     string `gorm:"type:varchar(20);not null"`
	Ip      string `gorm:"type:varchar(20);not null"`
	Load1   string `gorm:"type:varchar(100)"`
	Load5   string `gorm:"type:varchar(100)"`
	Load15  string `gorm:"type:varchar(100)"`
}

type Flow struct {
	Id          int    `gorm:"primary_key;auto_increment"`
	NowTime     string `gorm:"type:varchar(100);not null"`
	Lan         string `gorm:"type:varchar(20);not null"`
	Ip          string `gorm:"type:varchar(20);not null"`
	Name        string `gorm:"type:varchar(100)"`
	BytesSent   string `gorm:"type:varchar(100)"`
	BytesRecv   string `gorm:"type:varchar(100)"`
	PacketsSent string `gorm:"type:varchar(100)"`
	PacketsRecv string `gorm:"type:varchar(100)"`
	Errin       string `gorm:"type:varchar(100)"`
	Errout      string `gorm:"type:varchar(100)"`
	Dropin      string `gorm:"type:varchar(100)"`
	Dropout     string `gorm:"type:varchar(100)"`
	Fifoin      string `gorm:"type:varchar(100)"`
	Fifoout     string `gorm:"type:varchar(100)"`
}

type DiskUsed struct {
	Id                int    `gorm:"primary_key;auto_increment"`
	NowTime           string `gorm:"type:varchar(100);not null"`
	Lan               string `gorm:"type:varchar(20);not null"`
	Ip                string `gorm:"type:varchar(20);not null"`
	Path              string `gorm:"type:varchar(100)"`
	Fstype            string `gorm:"type:varchar(100)"`
	Total             string `gorm:"type:varchar(100)"`
	Free              string `gorm:"type:varchar(100)"`
	Used              string `gorm:"type:varchar(100)"`
	UsedPercent       string `gorm:"type:varchar(100)"`
	InodesTotal       string `gorm:"type:varchar(100)"`
	InodesUsed        string `gorm:"type:varchar(100)"`
	InodesFree        string `gorm:"type:varchar(100)"`
	InodesUsedPercent string `gorm:"type:varchar(100)"`
}

type DiskInfo struct {
	Id         int    `gorm:"primary_key;auto_increment"`
	NowTime    string `gorm:"type:varchar(100);not null"`
	Lan        string `gorm:"type:varchar(20);not null"`
	Ip         string `gorm:"type:varchar(20);not null"`
	Device     string `gorm:"type:varchar(100)"`
	Mountpoint string `gorm:"type:varchar(100)"`
	Fstype     string `gorm:"type:varchar(100)"`
	Opts       string `gorm:"type:varchar(100)"`
}

type CpuUsed struct {
	Id      int    `gorm:"primary_key;auto_increment"`
	NowTime string `gorm:"type:varchar(100);not null"`
	Lan     string `gorm:"type:varchar(20);not null"`
	Ip      string `gorm:"type:varchar(20);not null"`
	Percent string `gorm:"type:varchar(100)"`
}

type CpuInfo struct {
	Id         int    `gorm:"primary_key;auto_increment"`
	NowTime    string `gorm:"type:varchar(100);not null"`
	Lan        string `gorm:"type:varchar(20);not null"`
	Ip         string `gorm:"type:varchar(20);not null"`
	CPU        string `gorm:"type:varchar(100)"`
	VendorID   string `gorm:"type:varchar(100)"`
	Family     string `gorm:"type:varchar(100)"`
	Model      string `gorm:"type:varchar(100)"`
	Stepping   string `gorm:"type:varchar(100)"`
	PhysicalID string `gorm:"type:varchar(100)"`
	CoreID     string `gorm:"type:varchar(100)"`
	Cores      string `gorm:"type:varchar(100)"`
	ModelName  string `gorm:"type:varchar(100)"`
	Mhz        string `gorm:"type:varchar(100)"`
	CacheSize  string `gorm:"type:varchar(100)"`
	Flags      string `gorm:"type:varchar(100)"`
	Microcode  string `gorm:"type:varchar(100)"`
}

type NetWorkInfo struct {
	Id           int    `gorm:"primary_key;auto_increment"`
	NowTime      string `gorm:"type:varchar(100);not null"`
	Lan          string `gorm:"type:varchar(20);not null"`
	Ip           string `gorm:"type:varchar(20);not null"`
	MTU          string `gorm:"type:varchar(100)"`
	Name         string `gorm:"type:varchar(100)"`
	HardwareAddr string `gorm:"type:varchar(100)"`
	Flags        string `gorm:"type:varchar(100)"`
	Addrs        string `gorm:"type:varchar(100)"`
}

type Memory struct {
	Id             int    `gorm:"primary_key;auto_increment"`
	NowTime        string `gorm:"type:varchar(100);not null"`
	Lan            string `gorm:"type:varchar(20);not null"`
	Ip             string `gorm:"type:varchar(20);not null"`
	Total          string `gorm:"type:varchar(100)"`
	Available      string `gorm:"type:varchar(100)"`
	Used           string `gorm:"type:varchar(100)"`
	UsedPercent    string `gorm:"type:varchar(100)"`
	Free           string `gorm:"type:varchar(100)"`
	Active         string `gorm:"type:varchar(100)"`
	Inactive       string `gorm:"type:varchar(100)"`
	Wired          string `gorm:"type:varchar(100)"`
	Laundry        string `gorm:"type:varchar(100)"`
	Buffers        string `gorm:"type:varchar(100)"`
	Cached         string `gorm:"type:varchar(100)"`
	Writeback      string `gorm:"type:varchar(100)"`
	Dirty          string `gorm:"type:varchar(100)"`
	WritebackTmp   string `gorm:"type:varchar(100)"`
	Shared         string `gorm:"type:varchar(100)"`
	Slab           string `gorm:"type:varchar(100)"`
	PageTables     string `gorm:"type:varchar(100)"`
	SwapCached     string `gorm:"type:varchar(100)"`
	CommitLimit    string `gorm:"type:varchar(100)"`
	CommittedAS    string `gorm:"type:varchar(100)"`
	HighTotal      string `gorm:"type:varchar(100)"`
	HighFree       string `gorm:"type:varchar(100)"`
	LowTotal       string `gorm:"type:varchar(100)"`
	LowFree        string `gorm:"type:varchar(100)"`
	SwapTotal      string `gorm:"type:varchar(100)"`
	SwapFree       string `gorm:"type:varchar(100)"`
	Mapped         string `gorm:"type:varchar(100)"`
	VMallocTotal   string `gorm:"type:varchar(100)"`
	VMallocUsed    string `gorm:"type:varchar(100)"`
	VMallocChunk   string `gorm:"type:varchar(100)"`
	HugePagesTotal string `gorm:"type:varchar(100)"`
	HugePagesFree  string `gorm:"type:varchar(100)"`
	HugePageSize   string `gorm:"type:varchar(100)"`
}

func Check(con []string) bool {
	context := con[0] + ":" + con[1] + "@tcp(" + con[2] + ":" + con[3] + ")/" + con[4] + "?charset=utf8&parseTime=True&loc=Local"
	db, err := gorm.Open("mysql", context)
	//db, err := gorm.Open("mysql", "root:haishina@tcp(127.0.0.1:3306)/mgo?charset=utf8&parseTime=True&loc=Local")
	defer db.Close()
	if err != nil {
		return false
	} else {
		return true
	}
}

func Start(tableName string, datahead map[string]string, data interface{}, con []string) {
	context := con[0] + ":" + con[1] + "@tcp(" + con[2] + ":" + con[3] + ")/" + con[4] + "?charset=utf8&parseTime=True&loc=Local"
	db, err := gorm.Open("mysql", context)
	if err != nil {
		logs.PrintlnFile("Failure of database connection:"+fmt.Sprint(err), 5)
		return
	}
	defer db.Close()

	switch tableName {
	case "CpuUsed":
		redata := data.(interface{}).([]interface{})
		if !db.HasTable(&CpuUsed{}) {
			if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&CpuUsed{}).Error; err != nil {
				logs.PrintlnFile("Failure to create a new database table 'cpu_useds':"+fmt.Sprint(err), 4)
			}
		}
		cpuused := &CpuUsed{
			NowTime: datahead["NowTime"],
			Lan:     datahead["Lan"],
			Ip:      datahead["Ip"],
			Percent: fmt.Sprint(redata[0]),
		}
		if err := db.Create(cpuused).Error; err != nil {
			logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
		}
	case "NetWorkInfo":
		redata := data.(interface{}).([]interface{})
		if db.HasTable(&NetWorkInfo{}) {
			db.DropTable(&NetWorkInfo{})
		}
		if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&NetWorkInfo{}).Error; err != nil {
			logs.PrintlnFile("Failure to create a new database table 'net_work_infos':"+fmt.Sprint(err), 4)
		}

		for _, k := range redata {
			rek := k.(interface{}).(map[string]interface{})
			tmp := rek["addrs"].(interface{}).([]interface{})

			var adds string
			for i, j := range tmp {
				_j := j.(interface{}).(map[string]interface{})
				if i == len(tmp)-1 {
					adds = adds + fmt.Sprint(_j["addr"])
				} else {
					adds = adds + fmt.Sprint(_j["addr"]) + ","
				}
			}
			networkinfo := &NetWorkInfo{
				NowTime:      datahead["NowTime"],
				Lan:          datahead["Lan"],
				Ip:           datahead["Ip"],
				MTU:          fmt.Sprint(rek["mtu"]),
				Name:         fmt.Sprint(rek["name"]),
				HardwareAddr: fmt.Sprint(rek["hardwareaddr"]),
				Flags:        fmt.Sprint(rek["flags"]),
				Addrs:        adds,
			}
			if err := db.Create(networkinfo).Error; err != nil {
				logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
			}
		}
	case "CpuInfo":
		redata := data.(interface{}).([]interface{})
		if db.HasTable(&CpuInfo{}) {
			db.DropTable(&CpuInfo{})
		}
		if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&CpuInfo{}).Error; err != nil {
			logs.PrintlnFile("Failure to create a new database table 'cpu_infos':"+fmt.Sprint(err), 4)
		}

		for _, k := range redata {
			rek := k.(interface{}).(map[string]interface{})
			cpuinfo := &CpuInfo{
				NowTime:    datahead["NowTime"],
				Lan:        datahead["Lan"],
				Ip:         datahead["Ip"],
				CPU:        fmt.Sprint(rek["cpu"]),
				VendorID:   fmt.Sprint(rek["vendorId"]),
				Family:     fmt.Sprint(rek["family"]),
				Model:      fmt.Sprint(rek["model"]),
				Stepping:   fmt.Sprint(rek["stepping"]),
				PhysicalID: fmt.Sprint(rek["physicalId"]),
				CoreID:     fmt.Sprint(rek["coreId"]),
				Cores:      fmt.Sprint(rek["cores"]),
				ModelName:  fmt.Sprint(rek["modelName"]),
				Mhz:        fmt.Sprint(rek["mhz"]),
				CacheSize:  fmt.Sprint(rek["cacheSize"]),
				Flags:      fmt.Sprint(rek["flags"]),
				Microcode:  fmt.Sprint(rek["microcode"]),
			}
			if err := db.Create(cpuinfo).Error; err != nil {
				logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
			}
		}
	case "DiskInfo":
		redata := data.(interface{}).([]interface{})
		//if !db.HasTable(&DiskInfo{}) {
		//	if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&DiskInfo{}).Error; err != nil {
		//		panic(err)
		//	}
		//}
		if db.HasTable(&DiskInfo{}) {
			db.DropTable(&DiskInfo{})
		}
		if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&DiskInfo{}).Error; err != nil {
			logs.PrintlnFile("Failure to create a new database table 'disk_infos':"+fmt.Sprint(err), 4)
		}

		for _, k := range redata {
			rek := k.(interface{}).(map[string]interface{})
			diskinfo := &DiskInfo{
				NowTime:    datahead["NowTime"],
				Lan:        datahead["Lan"],
				Ip:         datahead["Ip"],
				Device:     fmt.Sprint(rek["device"]),
				Mountpoint: fmt.Sprint(rek["mountpoint"]),
				Fstype:     fmt.Sprint(rek["fstype"]),
				Opts:       fmt.Sprint(rek["opts"]),
			}
			if err := db.Create(diskinfo).Error; err != nil {
				logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
			}
		}
	case "Flow":
		redata := data.(interface{}).([]interface{})
		if !db.HasTable(&Flow{}) {
			if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&Flow{}).Error; err != nil {
				logs.PrintlnFile("Failure to create a new database table 'flows':"+fmt.Sprint(err), 4)
			}
		}

		for _, k := range redata {
			rek := k.(interface{}).(map[string]interface{})
			flow := &Flow{
				NowTime:     datahead["NowTime"],
				Lan:         datahead["Lan"],
				Ip:          datahead["Ip"],
				Name:        fmt.Sprint(rek["name"]),
				BytesSent:   fmt.Sprint(rek["bytesSent"]),
				BytesRecv:   fmt.Sprint(rek["bytesRecv"]),
				PacketsSent: fmt.Sprint(rek["packetsSent"]),
				PacketsRecv: fmt.Sprint(rek["packetsRecv"]),
				Errin:       fmt.Sprint(rek["errin"]),
				Errout:      fmt.Sprint(rek["errout"]),
				Dropin:      fmt.Sprint(rek["dropin"]),
				Dropout:     fmt.Sprint(rek["dropout"]),
				Fifoin:      fmt.Sprint(rek["fifoin"]),
				Fifoout:     fmt.Sprint(rek["fifoout"]),
			}
			if err := db.Create(flow).Error; err != nil {
				logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
			}
		}

	case "DiskUsed":
		redata := data.(interface{}).([]interface{})
		if !db.HasTable(&DiskUsed{}) {
			if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&DiskUsed{}).Error; err != nil {
				logs.PrintlnFile("Failure to create a new database table 'disk_useds':"+fmt.Sprint(err), 4)
			}
		}

		for _, k := range redata {
			rek := k.(interface{}).(map[string]interface{})
			diskUsed := &DiskUsed{
				NowTime:           datahead["NowTime"],
				Lan:               datahead["Lan"],
				Ip:                datahead["Ip"],
				Path:              fmt.Sprint(rek["path"]),
				Fstype:            fmt.Sprint(rek["fstype"]),
				Total:             fmt.Sprint(rek["total"]),
				Free:              fmt.Sprint(rek["free"]),
				Used:              fmt.Sprint(rek["used"]),
				UsedPercent:       fmt.Sprint(rek["usedPercent"]),
				InodesTotal:       fmt.Sprint(rek["inodesTotal"]),
				InodesUsed:        fmt.Sprint(rek["inodesUsed"]),
				InodesFree:        fmt.Sprint(rek["inodesFree"]),
				InodesUsedPercent: fmt.Sprint(rek["inodesUsedPercent"]),
			}

			if err := db.Create(diskUsed).Error; err != nil {
				logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
			}
		}
	case "Process":
		redata := data.(interface{}).(int)
		if !db.HasTable(&Process{}) {
			if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&Process{}).Error; err != nil {
				logs.PrintlnFile("Failure to create a new database table 'processes':"+fmt.Sprint(err), 4)
			}
		}

		process := &Process{
			NowTime: datahead["NowTime"],
			Lan:     datahead["Lan"],
			Ip:      datahead["Ip"],
			Process: fmt.Sprint(redata),
		}

		if err := db.Create(process).Error; err != nil {
			logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
		}
	case "Host":
		rehost := data.(interface{}).(map[string]interface{})
		if !db.HasTable(&Host{}) {
			if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&Host{}).Error; err != nil {
				logs.PrintlnFile("Failure to create a new database table 'hosts':"+fmt.Sprint(err), 4)
			}
		}

		host := &Host{
			NowTime:              datahead["NowTime"],
			Lan:                  datahead["Lan"],
			Ip:                   datahead["Ip"],
			Hostname:             fmt.Sprint(rehost["hostname"]),
			Uptime:               fmt.Sprint(rehost["uptime"]),
			BootTime:             fmt.Sprint(rehost["bootTime"]),
			Procs:                fmt.Sprint(rehost["procs"]),
			Os:                   fmt.Sprint(rehost["os"]),
			Platform:             fmt.Sprint(rehost["platform"]),
			PlatformFamily:       fmt.Sprint(rehost["platformFamily"]),
			PlatformVersion:      fmt.Sprint(rehost["platformVersion"]),
			KernelVersion:        fmt.Sprint(rehost["kernelVersion"]),
			VirtualizationSystem: fmt.Sprint(rehost["kernelVersion"]),
			VirtualizationRole:   fmt.Sprint(rehost["virtualizationRole"]),
			Hostid:               fmt.Sprint(rehost["hostid"]),
		}
		if err := db.Create(host).Error; err != nil {
			logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
		}
	case "CpuLoad":
		redata := data.(interface{}).(map[string]interface{})
		if !db.HasTable(&CpuLoad{}) {
			if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&CpuLoad{}).Error; err != nil {
				logs.PrintlnFile("Failure to create a new database table 'cpu_loads':"+fmt.Sprint(err), 4)
			}
		}

		cpuLoad := &CpuLoad{
			NowTime: datahead["NowTime"],
			Lan:     datahead["Lan"],
			Ip:      datahead["Ip"],
			Load1:   fmt.Sprint(redata["load1"]),
			Load5:   fmt.Sprint(redata["load5"]),
			Load15:  fmt.Sprint(redata["load15"]),
		}

		if err := db.Create(cpuLoad).Error; err != nil {
			logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
		}
	case "Memory":
		redata := data.(interface{}).(map[string]interface{})
		if !db.HasTable(&Memory{}) {
			if err := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&Memory{}).Error; err != nil {
				logs.PrintlnFile("Failure to create a new database table 'memories':"+fmt.Sprint(err), 4)
			}
		}

		memory := &Memory{
			NowTime:        datahead["NowTime"],
			Lan:            datahead["Lan"],
			Ip:             datahead["Ip"],
			Total:          fmt.Sprint(redata["total"]),
			Available:      fmt.Sprint(redata["available"]),
			Used:           fmt.Sprint(redata["used"]),
			UsedPercent:    fmt.Sprint(redata["usedPercent"]),
			Free:           fmt.Sprint(redata["free"]),
			Active:         fmt.Sprint(redata["active"]),
			Inactive:       fmt.Sprint(redata["inactive"]),
			Wired:          fmt.Sprint(redata["wired"]),
			Laundry:        fmt.Sprint(redata["laundry"]),
			Buffers:        fmt.Sprint(redata["buffers"]),
			Cached:         fmt.Sprint(redata["cached"]),
			Writeback:      fmt.Sprint(redata["writeback"]),
			Dirty:          fmt.Sprint(redata["dirty"]),
			WritebackTmp:   fmt.Sprint(redata["writebacktmp"]),
			Shared:         fmt.Sprint(redata["shared"]),
			Slab:           fmt.Sprint(redata["slab"]),
			PageTables:     fmt.Sprint(redata["pagetables"]),
			SwapCached:     fmt.Sprint(redata["swapcached"]),
			CommitLimit:    fmt.Sprint(redata["commitlimit"]),
			CommittedAS:    fmt.Sprint(redata["committedas"]),
			HighTotal:      fmt.Sprint(redata["hightotal"]),
			HighFree:       fmt.Sprint(redata["highfree"]),
			LowTotal:       fmt.Sprint(redata["lowtotal"]),
			LowFree:        fmt.Sprint(redata["lowfree"]),
			SwapTotal:      fmt.Sprint(redata["swaptotal"]),
			SwapFree:       fmt.Sprint(redata["swapfree"]),
			Mapped:         fmt.Sprint(redata["mapped"]),
			VMallocTotal:   fmt.Sprint(redata["mapped"]),
			VMallocUsed:    fmt.Sprint(redata["vmallocused"]),
			VMallocChunk:   fmt.Sprint(redata["vmallocchunk"]),
			HugePagesTotal: fmt.Sprint(redata["hugepagestotal"]),
			HugePagesFree:  fmt.Sprint(redata["hugepagesfree"]),
			HugePageSize:   fmt.Sprint(redata["hugepagesize"]),
		}

		if err := db.Create(memory).Error; err != nil {
			logs.PrintlnFile("Failure to insert data into database:"+fmt.Sprint(err), 4)
		}

	}
}
